package com.wn.common.base

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wn.common.model.SingleLiveData
import kotlinx.coroutines.*

/**
 * @Author: wn
 * @Date: 2022/12/13 17:06
 * @Description: viewModel的公共基类
 */
open class BaseViewModel : ViewModel() {
  // job的列表   销毁时  取消所有 Job
  private val jobs: MutableList<Job> = mutableListOf()

  // 标记网络loading状态
  // todo isLoading apiLaunch protected-->public protected
  protected val isLoading = SingleLiveData<Boolean>()

  /**
   * 扩展函数，用于viewModel中 将当前 job 添加到 list 参数中
   */
  private fun Job.addTo(list: MutableList<Job>): Job {
    list.add(this)
    return this
  }

  private fun <T> Deferred<T>.addTo(list: MutableList<Job>): Deferred<T> {
    list.add(this)
    return this
  }

  /**
   * 启用协程代码块 网络请求
   * suspend 挂起函数        -- lambda 中可以起 挂起函数
   * CoroutineScope扩展函数  -- 作用域  lambda 中可以起协程
   */
  protected fun apiLaunch(block: suspend CoroutineScope.() -> Unit) = viewModelScope.launch {
    isLoading.value = true
    block() // 挂起函数  带有 CoroutineScope
    isLoading.value = false
  }.addTo(jobs)

  /**
   * 带有返回值 -- 挂起或者协程中 使用
   * @param block [@kotlin.ExtensionFunctionType] SuspendFunction1<CoroutineScope, R>
   * @return R
   */
  protected suspend fun <R> apiLaunchDeferred(block: suspend CoroutineScope.() -> R): R =
    viewModelScope.async {
      isLoading.value = true
      val response = block() // 挂起函数  带有 CoroutineScope
      isLoading.value = false
      response
    }.addTo(jobs).await()


  /**
   * 取消所有 Job
   */
  override fun onCleared() {
    jobs.forEach { it.cancel() }
    super.onCleared()
  }
}